home *** CD-ROM | disk | FTP | other *** search
/ Chip 2007 January, February, March & April / Chip-Cover-CD-2007-02.iso / Pakiet bezpieczenstwa / mini Pentoo LiveCD 2006.1 / mpentoo-2006.1.iso / livecd.squashfs / usr / include / enlightenment / e_mmx.h < prev    next >
C/C++ Source or Header  |  2006-01-09  |  21KB  |  645 lines

  1. /*    mmx.h
  2.  
  3.     MultiMedia eXtensions GCC interface library for IA32.
  4.  
  5.     To use this library, simply include this header file
  6.     and compile with GCC.  You MUST have inlining enabled
  7.     in order for mmx_ok() to work; this can be done by
  8.     simply using -O on the GCC command line.
  9.  
  10.     Compiling with -DMMX_TRACE will cause detailed trace
  11.     output to be sent to stderr for each mmx operation.
  12.     This adds lots of code, and obviously slows execution to
  13.     a crawl, but can be very useful for debugging.
  14.  
  15.     THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY
  16.     EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT
  17.     LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY
  18.     AND FITNESS FOR ANY PARTICULAR PURPOSE.
  19.  
  20.     1997-98 by H. Dietz and R. Fisher
  21.  
  22.  History:
  23.     97-98*    R.Fisher    Early versions
  24.     980501    R.Fisher    Original Release
  25.     980611*    H.Dietz        Rewrite, correctly implementing inlines, and
  26.         R.Fisher     including direct register accesses.
  27.     980616    R.Fisher    Release of 980611 as 980616.
  28.     980714    R.Fisher    Minor corrections to Makefile, etc.
  29.     980715    R.Fisher    mmx_ok() now prevents optimizer from using
  30.                  clobbered values.
  31.                 mmx_ok() now checks if cpuid instruction is
  32.                  available before trying to use it.
  33.     980726*    R.Fisher    mm_support() searches for AMD 3DNow, Cyrix
  34.                  Extended MMX, and standard MMX.  It returns a
  35.                  value which is positive if any of these are
  36.                  supported, and can be masked with constants to
  37.                  see which.  mmx_ok() is now a call to this
  38.     980726*    R.Fisher    Added i2r support for shift functions
  39.     980919    R.Fisher    Fixed AMD extended feature recognition bug.
  40.     980921    R.Fisher    Added definition/check for _MMX_H.
  41.                 Added "float s[2]" to mmx_t for use with
  42.                   3DNow and EMMX.  So same mmx_t can be used.
  43.     981013    R.Fisher    Fixed cpuid function 1 bug (looked at wrong reg)
  44.                 Fixed psllq_i2r error in mmxtest.c
  45.  
  46.     * Unreleased (internal or interim) versions
  47.  
  48.  Notes:
  49.     It appears that the latest gas has the pand problem fixed, therefore
  50.       I'll undefine BROKEN_PAND by default.
  51.     String compares may be quicker than the multiple test/jumps in vendor
  52.       test sequence in mmx_ok(), but I'm not concerned with that right now.
  53.  
  54.  Acknowledgments:
  55.     Jussi Laako for pointing out the errors ultimately found to be
  56.       connected to the failure to notify the optimizer of clobbered values.
  57.     Roger Hardiman for reminding us that CPUID isn't everywhere, and that
  58.       someone may actually try to use this on a machine without CPUID.
  59.       Also for suggesting code for checking this.
  60.     Robert Dale for pointing out the AMD recognition bug.
  61.     Jimmy Mayfield and Carl Witty for pointing out the Intel recognition
  62.       bug.
  63.     Carl Witty for pointing out the psllq_i2r test bug.
  64. */
  65.  
  66. #ifndef _MMX_H
  67. #define _MMX_H
  68.  
  69. /*    Warning:  at this writing, the version of GAS packaged
  70.     with most Linux distributions does not handle the
  71.     parallel AND operation mnemonic correctly.  If the
  72.     symbol BROKEN_PAND is defined, a slower alternative
  73.     coding will be used.  If execution of mmxtest results
  74.     in an illegal instruction fault, define this symbol.
  75. */
  76. #undef    BROKEN_PAND
  77.  
  78.  
  79. /*    The type of an value that fits in an MMX register
  80.     (note that long long constant values MUST be suffixed
  81.      by LL and unsigned long long values by ULL, lest
  82.      they be truncated by the compiler)
  83. */
  84. typedef    union {
  85.     long long        q;    /* Quadword (64-bit) value */
  86.     unsigned long long    uq;    /* Unsigned Quadword */
  87.     int            d[2];    /* 2 Doubleword (32-bit) values */
  88.     unsigned int        ud[2];    /* 2 Unsigned Doubleword */
  89.     short            w[4];    /* 4 Word (16-bit) values */
  90.     unsigned short        uw[4];    /* 4 Unsigned Word */
  91.     char            b[8];    /* 8 Byte (8-bit) values */
  92.     unsigned char        ub[8];    /* 8 Unsigned Byte */
  93.     float            s[2];    /* Single-precision (32-bit) value */
  94. }  __attribute__ ((aligned (8))) mmx_t;
  95.  
  96. /*    Helper functions for the instruction macros that follow...
  97.     (note that memory-to-register, m2r, instructions are nearly
  98.      as efficient as register-to-register, r2r, instructions;
  99.      however, memory-to-memory instructions are really simulated
  100.      as a convenience, and are only 1/3 as efficient)
  101. */
  102.  
  103. /*    These macros are a lot simpler without the tracing...
  104. */
  105.  
  106. #define    mmx_i2r(op, imm, reg) \
  107.     __asm__ __volatile__ (#op " $" #imm ", %%" #reg \
  108.                   : /* nothing */ \
  109.                   : /* nothing */);
  110.  
  111. #define    mmx_m2r(op, mem, reg) \
  112.     __asm__ __volatile__ (#op " %0, %%" #reg \
  113.                   : /* nothing */ \
  114.                   : "m" (mem))
  115.  
  116. #define    mmx_r2m(op, reg, mem) \
  117.     __asm__ __volatile__ (#op " %%" #reg ", %0" \
  118.                   : "=m" (mem) \
  119.                   : /* nothing */ )
  120.  
  121. #define    mmx_r2r(op, regs, regd) \
  122.     __asm__ __volatile__ (#op " %" #regs ", %" #regd)
  123.  
  124. #define    mmx_m2m(op, mems, memd) \
  125.     __asm__ __volatile__ ("movq %0, %%mm0\n\t" \
  126.                   #op " %1, %%mm0\n\t" \
  127.                   "movq %%mm0, %0" \
  128.                   : "=m" (memd) \
  129.                   : "m" (mems))
  130.  
  131. /*    1x64 MOVe Quadword
  132.     (this is both a load and a store...
  133.      in fact, it is the only way to store)
  134. */
  135. #define    movq_m2r(var, reg)    mmx_m2r(movq, var, reg)
  136. #define    movq_r2m(reg, var)    mmx_r2m(movq, reg, var)
  137. #define    movq_r2r(regs, regd)    mmx_r2r(movq, regs, regd)
  138. #define    movq(vars, vard) \
  139.     __asm__ __volatile__ ("movq %1, %%mm0\n\t" \
  140.                   "movq %%mm0, %0" \
  141.                   : "=m" (vard) \
  142.                   : "m" (vars))
  143. #define    movntq_r2m(reg, var)   mmx_r2m(movntq, reg, var)
  144.  
  145.  
  146. /*    1x32 MOVe Doubleword
  147.     (like movq, this is both load and store...
  148.      but is most useful for moving things between
  149.      mmx registers and ordinary registers)
  150. */
  151. #define    movd_m2r(var, reg)    mmx_m2r(movd, var, reg)
  152. #define    movd_r2m(reg, var)    mmx_r2m(movd, reg, var)
  153. #define    movd_r2r(regs, regd)    mmx_r2r(movd, regs, regd)
  154. #define    movd(vars, vard) \
  155.     __asm__ __volatile__ ("movd %1, %%mm0\n\t" \
  156.                   "movd %%mm0, %0" \
  157.                   : "=m" (vard) \
  158.                   : "m" (vars))
  159.  
  160.  
  161. /*    2x32, 4x16, and 8x8 Parallel ADDs
  162. */
  163. #define    paddd_m2r(var, reg)    mmx_m2r(paddd, var, reg)
  164. #define    paddd_r2r(regs, regd)    mmx_r2r(paddd, regs, regd)
  165. #define    paddd(vars, vard)    mmx_m2m(paddd, vars, vard)
  166.  
  167. #define    paddw_m2r(var, reg)    mmx_m2r(paddw, var, reg)
  168. #define    paddw_r2r(regs, regd)    mmx_r2r(paddw, regs, regd)
  169. #define    paddw(vars, vard)    mmx_m2m(paddw, vars, vard)
  170.  
  171. #define    paddb_m2r(var, reg)    mmx_m2r(paddb, var, reg)
  172. #define    paddb_r2r(regs, regd)    mmx_r2r(paddb, regs, regd)
  173. #define    paddb(vars, vard)    mmx_m2m(paddb, vars, vard)
  174.  
  175.  
  176. /*    4x16 and 8x8 Parallel ADDs using Saturation arithmetic
  177. */
  178. #define    paddsw_m2r(var, reg)    mmx_m2r(paddsw, var, reg)
  179. #define    paddsw_r2r(regs, regd)    mmx_r2r(paddsw, regs, regd)
  180. #define    paddsw(vars, vard)    mmx_m2m(paddsw, vars, vard)
  181.  
  182. #define    paddsb_m2r(var, reg)    mmx_m2r(paddsb, var, reg)
  183. #define    paddsb_r2r(regs, regd)    mmx_r2r(paddsb, regs, regd)
  184. #define    paddsb(vars, vard)    mmx_m2m(paddsb, vars, vard)
  185.  
  186.  
  187. /*    4x16 and 8x8 Parallel ADDs using Unsigned Saturation arithmetic
  188. */
  189. #define    paddusw_m2r(var, reg)    mmx_m2r(paddusw, var, reg)
  190. #define    paddusw_r2r(regs, regd)    mmx_r2r(paddusw, regs, regd)
  191. #define    paddusw(vars, vard)    mmx_m2m(paddusw, vars, vard)
  192.  
  193. #define    paddusb_m2r(var, reg)    mmx_m2r(paddusb, var, reg)
  194. #define    paddusb_r2r(regs, regd)    mmx_r2r(paddusb, regs, regd)
  195. #define    paddusb(vars, vard)    mmx_m2m(paddusb, vars, vard)
  196.  
  197.  
  198. /*    2x32, 4x16, and 8x8 Parallel SUBs
  199. */
  200. #define    psubd_m2r(var, reg)    mmx_m2r(psubd, var, reg)
  201. #define    psubd_r2r(regs, regd)    mmx_r2r(psubd, regs, regd)
  202. #define    psubd(vars, vard)    mmx_m2m(psubd, vars, vard)
  203.  
  204. #define    psubw_m2r(var, reg)    mmx_m2r(psubw, var, reg)
  205. #define    psubw_r2r(regs, regd)    mmx_r2r(psubw, regs, regd)
  206. #define    psubw(vars, vard)    mmx_m2m(psubw, vars, vard)
  207.  
  208. #define    psubb_m2r(var, reg)    mmx_m2r(psubb, var, reg)
  209. #define    psubb_r2r(regs, regd)    mmx_r2r(psubb, regs, regd)
  210. #define    psubb(vars, vard)    mmx_m2m(psubb, vars, vard)
  211.  
  212.  
  213. /*    4x16 and 8x8 Parallel SUBs using Saturation arithmetic
  214. */
  215. #define    psubsw_m2r(var, reg)    mmx_m2r(psubsw, var, reg)
  216. #define    psubsw_r2r(regs, regd)    mmx_r2r(psubsw, regs, regd)
  217. #define    psubsw(vars, vard)    mmx_m2m(psubsw, vars, vard)
  218.  
  219. #define    psubsb_m2r(var, reg)    mmx_m2r(psubsb, var, reg)
  220. #define    psubsb_r2r(regs, regd)    mmx_r2r(psubsb, regs, regd)
  221. #define    psubsb(vars, vard)    mmx_m2m(psubsb, vars, vard)
  222.  
  223.  
  224. /*    4x16 and 8x8 Parallel SUBs using Unsigned Saturation arithmetic
  225. */
  226. #define    psubusw_m2r(var, reg)    mmx_m2r(psubusw, var, reg)
  227. #define    psubusw_r2r(regs, regd)    mmx_r2r(psubusw, regs, regd)
  228. #define    psubusw(vars, vard)    mmx_m2m(psubusw, vars, vard)
  229.  
  230. #define    psubusb_m2r(var, reg)    mmx_m2r(psubusb, var, reg)
  231. #define    psubusb_r2r(regs, regd)    mmx_r2r(psubusb, regs, regd)
  232. #define    psubusb(vars, vard)    mmx_m2m(psubusb, vars, vard)
  233.  
  234.  
  235. /*    4x16 Parallel MULs giving Low 4x16 portions of results
  236. */
  237. #define    pmullw_m2r(var, reg)    mmx_m2r(pmullw, var, reg)
  238. #define    pmullw_r2r(regs, regd)    mmx_r2r(pmullw, regs, regd)
  239. #define    pmullw(vars, vard)    mmx_m2m(pmullw, vars, vard)
  240.  
  241.  
  242. /*    4x16 Parallel MULs giving High 4x16 portions of results
  243. */
  244. #define    pmulhw_m2r(var, reg)    mmx_m2r(pmulhw, var, reg)
  245. #define    pmulhw_r2r(regs, regd)    mmx_r2r(pmulhw, regs, regd)
  246. #define    pmulhw(vars, vard)    mmx_m2m(pmulhw, vars, vard)
  247.  
  248.  
  249. /*    4x16->2x32 Parallel Mul-ADD
  250.     (muls like pmullw, then adds adjacent 16-bit fields
  251.      in the multiply result to make the final 2x32 result)
  252. */
  253. #define    pmaddwd_m2r(var, reg)    mmx_m2r(pmaddwd, var, reg)
  254. #define    pmaddwd_r2r(regs, regd)    mmx_r2r(pmaddwd, regs, regd)
  255. #define    pmaddwd(vars, vard)    mmx_m2m(pmaddwd, vars, vard)
  256.  
  257.  
  258. /*    1x64 bitwise AND
  259. */
  260. #ifdef    BROKEN_PAND
  261. #define    pand_m2r(var, reg) \
  262.     { \
  263.         mmx_m2r(pandn, (mmx_t) -1LL, reg); \
  264.         mmx_m2r(pandn, var, reg); \
  265.     }
  266. #define    pand_r2r(regs, regd) \
  267.     { \
  268.         mmx_m2r(pandn, (mmx_t) -1LL, regd); \
  269.         mmx_r2r(pandn, regs, regd) \
  270.     }
  271. #define    pand(vars, vard) \
  272.     { \
  273.         movq_m2r(vard, mm0); \
  274.         mmx_m2r(pandn, (mmx_t) -1LL, mm0); \
  275.         mmx_m2r(pandn, vars, mm0); \
  276.         movq_r2m(mm0, vard); \
  277.     }
  278. #else
  279. #define    pand_m2r(var, reg)    mmx_m2r(pand, var, reg)
  280. #define    pand_r2r(regs, regd)    mmx_r2r(pand, regs, regd)
  281. #define    pand(vars, vard)    mmx_m2m(pand, vars, vard)
  282. #endif
  283.  
  284.  
  285. /*    1x64 bitwise AND with Not the destination
  286. */
  287. #define    pandn_m2r(var, reg)    mmx_m2r(pandn, var, reg)
  288. #define    pandn_r2r(regs, regd)    mmx_r2r(pandn, regs, regd)
  289. #define    pandn(vars, vard)    mmx_m2m(pandn, vars, vard)
  290.  
  291.  
  292. /*    1x64 bitwise OR
  293. */
  294. #define    por_m2r(var, reg)    mmx_m2r(por, var, reg)
  295. #define    por_r2r(regs, regd)    mmx_r2r(por, regs, regd)
  296. #define    por(vars, vard)    mmx_m2m(por, vars, vard)
  297.  
  298.  
  299. /*    1x64 bitwise eXclusive OR
  300. */
  301. #define    pxor_m2r(var, reg)    mmx_m2r(pxor, var, reg)
  302. #define    pxor_r2r(regs, regd)    mmx_r2r(pxor, regs, regd)
  303. #define    pxor(vars, vard)    mmx_m2m(pxor, vars, vard)
  304.  
  305.  
  306. /*    2x32, 4x16, and 8x8 Parallel CoMPare for EQuality
  307.     (resulting fields are either 0 or -1)
  308. */
  309. #define    pcmpeqd_m2r(var, reg)    mmx_m2r(pcmpeqd, var, reg)
  310. #define    pcmpeqd_r2r(regs, regd)    mmx_r2r(pcmpeqd, regs, regd)
  311. #define    pcmpeqd(vars, vard)    mmx_m2m(pcmpeqd, vars, vard)
  312.  
  313. #define    pcmpeqw_m2r(var, reg)    mmx_m2r(pcmpeqw, var, reg)
  314. #define    pcmpeqw_r2r(regs, regd)    mmx_r2r(pcmpeqw, regs, regd)
  315. #define    pcmpeqw(vars, vard)    mmx_m2m(pcmpeqw, vars, vard)
  316.  
  317. #define    pcmpeqb_m2r(var, reg)    mmx_m2r(pcmpeqb, var, reg)
  318. #define    pcmpeqb_r2r(regs, regd)    mmx_r2r(pcmpeqb, regs, regd)
  319. #define    pcmpeqb(vars, vard)    mmx_m2m(pcmpeqb, vars, vard)
  320.  
  321.  
  322. /*    2x32, 4x16, and 8x8 Parallel CoMPare for Greater Than
  323.     (resulting fields are either 0 or -1)
  324. */
  325. #define    pcmpgtd_m2r(var, reg)    mmx_m2r(pcmpgtd, var, reg)
  326. #define    pcmpgtd_r2r(regs, regd)    mmx_r2r(pcmpgtd, regs, regd)
  327. #define    pcmpgtd(vars, vard)    mmx_m2m(pcmpgtd, vars, vard)
  328.  
  329. #define    pcmpgtw_m2r(var, reg)    mmx_m2r(pcmpgtw, var, reg)
  330. #define    pcmpgtw_r2r(regs, regd)    mmx_r2r(pcmpgtw, regs, regd)
  331. #define    pcmpgtw(vars, vard)    mmx_m2m(pcmpgtw, vars, vard)
  332.  
  333. #define    pcmpgtb_m2r(var, reg)    mmx_m2r(pcmpgtb, var, reg)
  334. #define    pcmpgtb_r2r(regs, regd)    mmx_r2r(pcmpgtb, regs, regd)
  335. #define    pcmpgtb(vars, vard)    mmx_m2m(pcmpgtb, vars, vard)
  336.  
  337.  
  338. /*    1x64, 2x32, and 4x16 Parallel Shift Left Logical
  339. */
  340. #define    psllq_i2r(imm, reg)    mmx_i2r(psllq, imm, reg)
  341. #define    psllq_m2r(var, reg)    mmx_m2r(psllq, var, reg)
  342. #define    psllq_r2r(regs, regd)    mmx_r2r(psllq, regs, regd)
  343. #define    psllq(vars, vard)    mmx_m2m(psllq, vars, vard)
  344.  
  345. #define    pslld_i2r(imm, reg)    mmx_i2r(pslld, imm, reg)
  346. #define    pslld_m2r(var, reg)    mmx_m2r(pslld, var, reg)
  347. #define    pslld_r2r(regs, regd)    mmx_r2r(pslld, regs, regd)
  348. #define    pslld(vars, vard)    mmx_m2m(pslld, vars, vard)
  349.  
  350. #define    psllw_i2r(imm, reg)    mmx_i2r(psllw, imm, reg)
  351. #define    psllw_m2r(var, reg)    mmx_m2r(psllw, var, reg)
  352. #define    psllw_r2r(regs, regd)    mmx_r2r(psllw, regs, regd)
  353. #define    psllw(vars, vard)    mmx_m2m(psllw, vars, vard)
  354.  
  355.  
  356. /*    1x64, 2x32, and 4x16 Parallel Shift Right Logical
  357. */
  358. #define    psrlq_i2r(imm, reg)    mmx_i2r(psrlq, imm, reg)
  359. #define    psrlq_m2r(var, reg)    mmx_m2r(psrlq, var, reg)
  360. #define    psrlq_r2r(regs, regd)    mmx_r2r(psrlq, regs, regd)
  361. #define    psrlq(vars, vard)    mmx_m2m(psrlq, vars, vard)
  362.  
  363. #define    psrld_i2r(imm, reg)    mmx_i2r(psrld, imm, reg)
  364. #define    psrld_m2r(var, reg)    mmx_m2r(psrld, var, reg)
  365. #define    psrld_r2r(regs, regd)    mmx_r2r(psrld, regs, regd)
  366. #define    psrld(vars, vard)    mmx_m2m(psrld, vars, vard)
  367.  
  368. #define    psrlw_i2r(imm, reg)    mmx_i2r(psrlw, imm, reg)
  369. #define    psrlw_m2r(var, reg)    mmx_m2r(psrlw, var, reg)
  370. #define    psrlw_r2r(regs, regd)    mmx_r2r(psrlw, regs, regd)
  371. #define    psrlw(vars, vard)    mmx_m2m(psrlw, vars, vard)
  372.  
  373.  
  374. /*    2x32 and 4x16 Parallel Shift Right Arithmetic
  375. */
  376. #define    psrad_i2r(imm, reg)    mmx_i2r(psrad, imm, reg)
  377. #define    psrad_m2r(var, reg)    mmx_m2r(psrad, var, reg)
  378. #define    psrad_r2r(regs, regd)    mmx_r2r(psrad, regs, regd)
  379. #define    psrad(vars, vard)    mmx_m2m(psrad, vars, vard)
  380.  
  381. #define    psraw_i2r(imm, reg)    mmx_i2r(psraw, imm, reg)
  382. #define    psraw_m2r(var, reg)    mmx_m2r(psraw, var, reg)
  383. #define    psraw_r2r(regs, regd)    mmx_r2r(psraw, regs, regd)
  384. #define    psraw(vars, vard)    mmx_m2m(psraw, vars, vard)
  385.  
  386.  
  387. /*    2x32->4x16 and 4x16->8x8 PACK and Signed Saturate
  388.     (packs source and dest fields into dest in that order)
  389. */
  390. #define    packssdw_m2r(var, reg)    mmx_m2r(packssdw, var, reg)
  391. #define    packssdw_r2r(regs, regd) mmx_r2r(packssdw, regs, regd)
  392. #define    packssdw(vars, vard)    mmx_m2m(packssdw, vars, vard)
  393.  
  394. #define    packsswb_m2r(var, reg)    mmx_m2r(packsswb, var, reg)
  395. #define    packsswb_r2r(regs, regd) mmx_r2r(packsswb, regs, regd)
  396. #define    packsswb(vars, vard)    mmx_m2m(packsswb, vars, vard)
  397.  
  398.  
  399. /*    4x16->8x8 PACK and Unsigned Saturate
  400.     (packs source and dest fields into dest in that order)
  401. */
  402. #define    packuswb_m2r(var, reg)    mmx_m2r(packuswb, var, reg)
  403. #define    packuswb_r2r(regs, regd) mmx_r2r(packuswb, regs, regd)
  404. #define    packuswb(vars, vard)    mmx_m2m(packuswb, vars, vard)
  405.  
  406.  
  407. /*    2x32->1x64, 4x16->2x32, and 8x8->4x16 UNPaCK Low
  408.     (interleaves low half of dest with low half of source
  409.      as padding in each result field)
  410. */
  411. #define    punpckldq_m2r(var, reg)    mmx_m2r(punpckldq, var, reg)
  412. #define    punpckldq_r2r(regs, regd) mmx_r2r(punpckldq, regs, regd)
  413. #define    punpckldq(vars, vard)    mmx_m2m(punpckldq, vars, vard)
  414.  
  415. #define    punpcklwd_m2r(var, reg)    mmx_m2r(punpcklwd, var, reg)
  416. #define    punpcklwd_r2r(regs, regd) mmx_r2r(punpcklwd, regs, regd)
  417. #define    punpcklwd(vars, vard)    mmx_m2m(punpcklwd, vars, vard)
  418.  
  419. #define    punpcklbw_m2r(var, reg)    mmx_m2r(punpcklbw, var, reg)
  420. #define    punpcklbw_r2r(regs, regd) mmx_r2r(punpcklbw, regs, regd)
  421. #define    punpcklbw(vars, vard)    mmx_m2m(punpcklbw, vars, vard)
  422.  
  423.  
  424. /*    2x32->1x64, 4x16->2x32, and 8x8->4x16 UNPaCK High
  425.     (interleaves high half of dest with high half of source
  426.      as padding in each result field)
  427. */
  428. #define    punpckhdq_m2r(var, reg)    mmx_m2r(punpckhdq, var, reg)
  429. #define    punpckhdq_r2r(regs, regd) mmx_r2r(punpckhdq, regs, regd)
  430. #define    punpckhdq(vars, vard)    mmx_m2m(punpckhdq, vars, vard)
  431.  
  432. #define    punpckhwd_m2r(var, reg)    mmx_m2r(punpckhwd, var, reg)
  433. #define    punpckhwd_r2r(regs, regd) mmx_r2r(punpckhwd, regs, regd)
  434. #define    punpckhwd(vars, vard)    mmx_m2m(punpckhwd, vars, vard)
  435.  
  436. #define    punpckhbw_m2r(var, reg)    mmx_m2r(punpckhbw, var, reg)
  437. #define    punpckhbw_r2r(regs, regd) mmx_r2r(punpckhbw, regs, regd)
  438. #define    punpckhbw(vars, vard)    mmx_m2m(punpckhbw, vars, vard)
  439.  
  440. #define MOVE_8DWORDS_MMX(src,dst) \
  441.        __asm__ ( \
  442.         "movq (%1), %%mm0 \n" \
  443.         "movq 0x8(%1), %%mm1 \n" \
  444.          "movq 0x10(%1), %%mm2 \n" \
  445.         "movq 0x18(%1), %%mm3 \n" \
  446.         "movq %%mm0, (%0) \n" \
  447.         "movq %%mm1, 0x8(%0) \n" \
  448.         "movq %%mm2, 0x10(%0) \n" \
  449.         "movq %%mm3, 0x18(%0) \n" \
  450.         : \
  451.         : "q" (dst), "r" (src) \
  452.         : "memory",  "st");
  453.  
  454. #define MOVE_10DWORDS_MMX(src,dst) \
  455.        __asm__ ( \
  456.         "movq (%1), %%mm0 \n" \
  457.         "movq 0x8(%1), %%mm1 \n" \
  458.          "movq 0x10(%1), %%mm2 \n" \
  459.         "movq 0x18(%1), %%mm3 \n" \
  460.         "movq 0x20(%1), %%mm4 \n" \
  461.         "movq %%mm0, (%0) \n" \
  462.         "movq %%mm1, 0x8(%0) \n" \
  463.         "movq %%mm2, 0x10(%0) \n" \
  464.         "movq %%mm3, 0x18(%0) \n" \
  465.         "movq %%mm4, 0x20(%0) \n" \
  466.         : \
  467.         : "q" (dst), "r" (src) \
  468.         : "memory",  "st");
  469.  
  470. #define MOVE_16DWORDS_MMX(src,dst) \
  471.        __asm__ ( \
  472.         "movq (%1), %%mm0 \n" \
  473.         "movq 0x8(%1), %%mm1 \n" \
  474.          "movq 0x10(%1), %%mm2 \n" \
  475.         "movq 0x18(%1), %%mm3 \n" \
  476.         "movq 0x20(%1), %%mm4 \n" \
  477.         "movq 0x28(%1), %%mm5 \n" \
  478.         "movq 0x30(%1), %%mm6 \n" \
  479.         "movq 0x38(%1), %%mm7 \n" \
  480.         "movq %%mm0, (%0) \n" \
  481.         "movq %%mm1, 0x8(%0) \n" \
  482.         "movq %%mm2, 0x10(%0) \n" \
  483.         "movq %%mm3, 0x18(%0) \n" \
  484.         "movq %%mm4, 0x20(%0) \n" \
  485.         "movq %%mm5, 0x28(%0) \n" \
  486.         "movq %%mm6, 0x30(%0) \n" \
  487.         "movq %%mm7, 0x38(%0) \n" \
  488.         : \
  489.         : "q" (dst), "r" (src) \
  490.         : "memory",  "st");
  491.  
  492. #define MOVE_16DWORDS_MMX2(src,dst) \
  493.        __asm__ ( \
  494.         "movq (%1), %%mm0 \n" \
  495.         "movq 0x8(%1), %%mm1 \n" \
  496.          "movq 0x10(%1), %%mm2 \n" \
  497.         "movq 0x18(%1), %%mm3 \n" \
  498.         "movq 0x20(%1), %%mm4 \n" \
  499.         "movq 0x28(%1), %%mm5 \n" \
  500.         "movq 0x30(%1), %%mm6 \n" \
  501.         "movq 0x38(%1), %%mm7 \n" \
  502.         "movntq %%mm0, (%0) \n" \
  503.         "movntq %%mm1, 0x8(%0) \n" \
  504.         "movntq %%mm2, 0x10(%0) \n" \
  505.         "movntq %%mm3, 0x18(%0) \n" \
  506.         "movntq %%mm4, 0x20(%0) \n" \
  507.         "movntq %%mm5, 0x28(%0) \n" \
  508.         "movntq %%mm6, 0x30(%0) \n" \
  509.         "movntq %%mm7, 0x38(%0) \n" \
  510.         : \
  511.         : "q" (dst), "r" (src) \
  512.         : "memory",  "st");
  513.  
  514. /*    Empty MMx State
  515.     (used to clean-up when going from mmx to float use
  516.      of the registers that are shared by both; note that
  517.      there is no float-to-mmx operation needed, because
  518.      only the float tag word info is corruptible)
  519. */
  520.  
  521. #define    emms()            __asm__ __volatile__ ("emms":::"memory")
  522. #define    sfence()        __asm__ __volatile__ ("sfence":::"memory")
  523.  
  524. /* additions to detect mmx - */
  525. /* Raster <raster@rasterman.com> */
  526.  
  527. #define CPUID_MMX  (1 << 23) /* flags: mmx */
  528. #define CPUID_SSE  (1 << 25) /* flags: xmm */
  529. #define CPUID_SSE2 (1 << 26) /* flags: ? */
  530.  
  531. #ifdef __amd64
  532. #define have_cpuid(cpuid_ret) \
  533.      __asm__ __volatile__ ( \
  534.                   ".align 32               \n" \
  535.                   "  pushq %%rbx           \n" \
  536.                   "  pushfq                \n" \
  537.                   "  popq %%rax            \n" \
  538.                   "  movq %%rax, %%rbx     \n" \
  539.                   "  xorq $0x200000, %%rax \n" \
  540.                   "  pushq %%rax           \n" \
  541.                   "  popfq                 \n" \
  542.                   "  pushfq                \n" \
  543.                   "  popq %%rax            \n" \
  544.                   "  cmpq %%rax, %%rbx     \n" \
  545.                   "  je 1f                 \n" \
  546.                   "  movl $1, %0           \n" \
  547.                   "  jmp 2f                \n" \
  548.                   "1:                      \n" \
  549.                   "  movl $0, %0           \n" \
  550.                   "2:                      \n" \
  551.                   "  popq %%rbx            \n" \
  552.                   : "=m" (cpuid_ret)           \
  553.                   );
  554.  
  555. #define get_cpuid(cpuid_ret) \
  556.      __asm__ __volatile__ ( \
  557.                   ".align 32               \n" \
  558.                   "  pushq %%rax           \n" \
  559.                   "  movl $1, %%eax        \n" \
  560.                   "  cpuid                 \n" \
  561.                   "  test $0x00800000, %%edx\n" \
  562.                   "1:                      \n" \
  563.                   "  movl %%edx, %0        \n" \
  564.                   "  jmp 2f                \n" \
  565.                   "2:                      \n" \
  566.                   "  movl $0, %0           \n" \
  567.                   "  popq %%rax            \n" \
  568.                   : "=m" (cpuid_ret)           \
  569.                   );
  570. #else
  571. #define have_cpuid(cpuid_ret) \
  572.      __asm__ __volatile__ ( \
  573.                   ".align 32               \n" \
  574.                   "  pushl %%ebx           \n" \
  575.                   "  pushfl                \n" \
  576.                   "  popl %%eax            \n" \
  577.                   "  movl %%eax, %%ebx     \n" \
  578.                   "  xorl $0x200000, %%eax \n" \
  579.                   "  pushl %%eax           \n" \
  580.                   "  popfl                 \n" \
  581.                   "  pushfl                \n" \
  582.                   "  popl %%eax            \n" \
  583.                   "  cmpl %%eax, %%ebx     \n" \
  584.                   "  je 1f                 \n" \
  585.                   "  movl $1, %0           \n" \
  586.                   "  jmp 2f                \n" \
  587.                   "1:                      \n" \
  588.                   "  movl $0, %0           \n" \
  589.                   "2:                      \n" \
  590.                   "  popl %%ebx            \n" \
  591.                   : "=m" (cpuid_ret)           \
  592.                   );
  593.  
  594. #define get_cpuid(cpuid_ret) \
  595.      __asm__ __volatile__ ( \
  596.                   ".align 32               \n" \
  597.                   "  pushl %%eax           \n" \
  598.                   "  movl $1, %%eax        \n" \
  599.                   "  cpuid                 \n" \
  600.                   "  test $0x00800000, %%edx\n" \
  601.                   "1:                      \n" \
  602.                   "  movl %%edx, %0        \n" \
  603.                   "  jmp 2f                \n" \
  604.                   "2:                      \n" \
  605.                   "  movl $0, %0           \n" \
  606.                   "  popl %%eax            \n" \
  607.                   : "=m" (cpuid_ret)           \
  608.                   );
  609. #endif
  610.  
  611. /* P3 instructions - need to figure how to detect? */
  612. #define prefetch(var) \
  613.     __asm__ __volatile__ ( \
  614.                  "prefetchnta (%0) \n" \
  615.                  : \
  616.                  : "r" (var) \
  617.                  );
  618. #define prefetch0(var) \
  619.     __asm__ __volatile__ ( \
  620.                  "prefetcht0 (%0) \n" \
  621.                  : \
  622.                  : "r" (var) \
  623.                  );
  624. #define prefetch1(var) \
  625.     __asm__ __volatile__ ( \
  626.                  "prefetcht1 (%0) \n" \
  627.                  : \
  628.                  : "r" (var) \
  629.                  );
  630. #define prefetch2(var) \
  631.     __asm__ __volatile__ ( \
  632.                  "prefetcht2 (%0) \n" \
  633.                  : \
  634.                  : "r" (var) \
  635.                  );
  636. #define pshufw(r1, r2, imm) \
  637.     __asm__ __volatile__ ( \
  638.                  "pshufw $" #imm ", %" #r1 ", %" #r2 " \n" \
  639.                  );
  640.  
  641. /* end additions */
  642.  
  643. #endif
  644.  
  645.